/*
 ============================================================================
 Name		: GaborJet.cpp
 Author	  : Lenka Litvova
 Version	 : 1.0
 Copyright   : 2008
 Description : CGaborJet implementation
 ============================================================================
 */

#include "GaborJet.h"
#include <e32math.h> //matematic function
#include <bautils.h> //for BaflUtils, link against: bafl.lib
#include <COEMAIN.H> //for CCoeEnv, link against: cone.lib
#include "GaborFilter.h"

#include "Globals.h"

CGaborJet::CGaborJet()
	{
	// No implementation required
	}

CGaborJet::~CGaborJet()
	{
		delete iValues;
	}

CGaborJet* CGaborJet::NewLC(CNokiaCVImage *aImage, TPoint aFaceFeature, TInt aSigma,
						    TInt aRadius, TInt aFreqs, TInt aMinFreq, TInt aMaxFreq,
							TInt aAngles)
	{
	CGaborJet* self = new (ELeave) CGaborJet();
	CleanupStack::PushL(self);
	self->ConstructL(aImage, aFaceFeature, aSigma, aRadius, aFreqs, aMinFreq, aMaxFreq, aAngles);
	return self;
	}

CGaborJet* CGaborJet::NewL(CNokiaCVImage *aImage, TPoint aFaceFeature, TInt aSigma,
						   TInt aRadius, TInt aFreqs, TInt aMinFreq, TInt aMaxFreq,
						   TInt aAngles)
	{
	CGaborJet* self = CGaborJet::NewLC(aImage, aFaceFeature, aSigma, aRadius, aFreqs, aMinFreq, aMaxFreq, aAngles);
	CleanupStack::Pop(); // self;
	return self;
	}

void CGaborJet::ConstructL(CNokiaCVImage *aImage, TPoint aFaceFeature, TInt aSigma,
						   TInt aRadius, TInt aFreqs, TInt aMinFreq, TInt aMaxFreq,
						   TInt aAngles)
	{
		 TReal32 sigma = aSigma*KPi*KPi;
	
		 //alokacia
		 iValues = new(ELeave)CArrayFixFlat<TReal>(aAngles*aFreqs);
		 TInt counter = 0;
		 
		 //vypocet hodnoty ako konvolucia obrazka s filtrom
		 TInt x, y;		// iterating over location
		 TInt a, f;		// iterating over angles and frequencies
		 TInt h, i, j;	// iterating over filter field
		 TReal32	sumI, sumR;	// sumy imaginarnych a realnych casti parts
		 	               
		 h = 0;
			
		 //vypocet
	     for ( a = 0; a < aAngles; a++ )
	     {
			 // vypocet uhla - hybe sa od 0 po PI v pravidelnych intervaloch
	         TReal angle = a * KPi /aAngles;

	            for ( f = 0; f < aFreqs; f++ )
	            {
	                // vypocet frekvencie
	                TReal freq = aMinFreq + ( f * ( aMaxFreq - aMinFreq ) ) / aFreqs;

	                //vytvorenie filtra
	                CGaborFilter *filter = CGaborFilter::NewL(aRadius, angle, freq, sigma, 0);
	                CleanupStack::PushL(filter);
	                
	                //vypocet jednotlivych hodnot filtra alebo ich nacitanie zo suboru, ak uz existuje	                
	                RFile file;
	                TBufC<50> Buf1 (KFilterDirectory);
	                TPtr pointer = Buf1.Des();
	                pointer.Append(_L("Filter_"));
	                pointer.AppendNum(aSigma);
	                pointer.Append(_L("_"));
	                pointer.AppendNum(aRadius);
	                pointer.Append(_L("_"));
	                pointer.AppendNum(aFreqs);
	                pointer.Append(_L("_"));
	                pointer.AppendNum(aMinFreq);
	                pointer.Append(_L("_"));
	                pointer.AppendNum(aMaxFreq);
	                pointer.Append(_L("_"));
	                pointer.AppendNum(aAngles);
	                pointer.Append(_L("x"));
	                pointer.AppendNum(counter);
	                	                
	                
	                if (BaflUtils::FileExists(CCoeEnv::Static()->FsSession(),pointer)) // file does not exist - create it
	                {
	                	filter->LoadFromFileL(pointer);
	                }
	                else
	                {
						User::LeaveIfError(file.Create(CCoeEnv::Static()->FsSession(),pointer,EFileWrite));
	                    file.Close();
	                    filter->Compute();
	                    filter->SaveToFileL(pointer);
	                }
	                	                             
	                sumR = 0.0;
	                sumI = 0.0;

	                // zaciatok v lavom hornom rohu filtrovanej lokacie
	                y = aFaceFeature.iY - aRadius;
	                for ( TInt gy = y; gy < y + 2 * aRadius; gy++ )
	                {
						//kontrola prekrocenia hranic
	                    if ( gy < 0 || gy >= aImage->Size().iHeight)
	                    	break;

	                    //posun k lokalnym suradniciam bodu filtra
	                    i = gy - y;

	                    x = aFaceFeature.iX - aRadius;
	                    for (TInt gx = x; gx < x + 2 * aRadius; gx++ )
	                    {
							//kontrola prekrocenia hranic
	                        if ( gx < 0 || gx >= aImage->Size().iWidth)
	                        	break;

	                        //posun k lokalnym suradniciam bodu filtra
	                    	j = gx - x;

	                    	TRgb c;
	                    	TPoint p = TPoint(gx, gy);
	                    	aImage->GetPixel(c, p);	 
	                    	TInt c_red = c.Red();
	                    	TInt c_green = c.Green();
	                    	TInt c_blue = c.Blue();
	                    	TReal red = c.Red()*0.3;
	                    	TReal green = c.Green()*0.59;
	                    	TReal blue = c.Blue()*0.11;
	                        TReal g = c.Red()*0.3 + c.Green()*0.59+ c.Blue()*0.11; 
	                         //double g = (c.getRed() + c.getGreen() + c.getBlue());
	                        TReal32 temp = filter->GetReal(j,i);
	                        TReal32 temp2 = filter->GetImaginary(j,i);
	                        sumR = sumR + g * filter->GetReal(j,i);
	                        sumI = sumI + g * filter->GetImaginary(j,i);
	                    }
	                }
	                TReal temp2;
	                Math::Sqrt(temp2, (sumR*sumR)+ (sumI*sumI));
	                iValues->AppendL(temp2);
	                counter++;
	                
	                CleanupStack::PopAndDestroy(filter);
	        }// frekvencia
	     } // uhol
	}
	     
	TInt CGaborJet::GetSize()
	{
		return iValues->Count();
	}
	     
	TReal CGaborJet::GetSimilarity(CGaborJet *aJet)
	{
	    if( iValues->Count() != aJet->GetSize())
	    	return 0;

	    TReal cit = 0;
	    TReal men1 = 0;
	    TReal men2 = 0;

	    for(TInt i=0;i<iValues->Count();i++)
	    {
			cit = cit + iValues->At(i)* aJet->GetValue(i);
	        men1 = men1 + iValues->At(i)* iValues->At(i);
	        men2 = men2 + aJet->GetValue(i)* aJet->GetValue(i);
	    }

	    TReal temp = 0.0;
	    TReal test = 0.0;
	    Math::Sqrt(temp, men1*men2);
	    return (cit / temp);
	}

void CGaborJet::SetValuesL(CArrayFixFlat<TReal> *aValues)
	{
		delete iValues;
		iValues = new(ELeave)CArrayFixFlat<TReal>(aValues->Count());
		for(TInt i=0;i<aValues->Count();i++)
		{
			iValues->AppendL(aValues->At(i));
		}
	}
